package com.toobigtofail.palette
{
	import com.toobigtofail.placeholders.Placeholder;
	import com.toobigtofail.placeholders.PlankPlaceholder;
	import com.toobigtofail.placeholders.WedgePlaceholder;
	import com.toobigtofail.utility.Level;
	
	import fabulaexmachina.box2fp.graphics.SuperGraphiclist;
	
	import flash.utils.Dictionary;
	import flash.utils.getDefinitionByName;
	import flash.utils.getQualifiedClassName;
	
	import net.flashpunk.Entity;
	import net.flashpunk.FP;
	import net.flashpunk.graphics.Image;
	import net.flashpunk.graphics.Text;
	import net.flashpunk.utils.Draw;
	import net.flashpunk.utils.Input;
	
	public class Tray extends Entity
	{
		[Embed(source="/assets/gfx/tray_handle.png")] private static const TRAY_HANDLE_PNG:Class;
		
		private static const ITEM_HANDLE_X_OFFSET:uint = 15;
		private static const ITEM_EDIT_BTN_X_OFFSET:uint = 30;
		private static const MAX_ITEM_COUNT:uint = 99;
		
		private var _handle:Entity;
		private var _isOpen:Boolean = false;
		private var _items:Dictionary = new Dictionary;
		private var _selectedItemType:String = null;
		
		private var _isEdit:Boolean = false;
		
		public function Tray(isEdit:Boolean = false)
		{
			_isEdit = isEdit;
			var handleImage:Image = new Image(TRAY_HANDLE_PNG);
			
			width = 200;
			height = FP.screen.height;
			
			y = 0;
			x = FP.screen.width - handleImage.width;
			_handle = new Entity(x, y, handleImage);
			_handle.width = handleImage.width;
			_handle.height = handleImage.height;
		
			if (isEdit) {
				for each (var classRef:Class in Level.ALL_PLACEHOLDERS) {
					addItem(new classRef(0,0), 1);
				}
			}
		}
		
		public function addItem(item:Placeholder, num:uint=1):void {
			var className:String = getQualifiedClassName(item);
			if (!_items[className]) {
				item.locked = true;
				var plus:PlaceholderEditButton = new PlaceholderEditButton(this, className, 0, 0, "plus");
				var minus:PlaceholderEditButton = new PlaceholderEditButton(this, className, 0, 0, "minus");
				_items[className] = {item: item, count: num, plusBtn: plus, minusBtn: minus};
			}
			else {
				addItemType(className, num);
			}
		}
		
		internal function addItemType(itemType:String, num:uint=1):void {
			var item:Object = _items[itemType];
			if (item) {
				item.count += num;
				item.count = Math.min(item.count, MAX_ITEM_COUNT);
			}
		}
		
		internal function subtractItemType(itemType:String, num:uint=1):Object {
			var item:Object = _items[itemType];
			if(item) {
				item.count-=num;
				if (item.count <= 0) {
					if (!_isEdit) {
						world.remove(item.item);
						delete _items[itemType];
					}
					else {
						item.count = 0;
					}
				}
				return item;
			}
			return null;
		}
		
		override public function added():void {
			super.added();
			
			world.add(_handle);
			
			var y:int = this.y + 50;
			for each (var key:String in getOrderedItemKeys()) {
				var item:Placeholder = _items[key].item as Placeholder;
				
				var itemX:uint = this.x + _handle.width + ITEM_HANDLE_X_OFFSET;
				if (_isEdit) {
					var plusBtn:PlaceholderEditButton = _items[key].plusBtn as PlaceholderEditButton;
					plusBtn.x = itemX;
					plusBtn.y = y + item.halfHeight;
					
					var minusBtn:PlaceholderEditButton = _items[key].minusBtn as PlaceholderEditButton;
					minusBtn.x = itemX;
					minusBtn.y = y + item.halfHeight + plusBtn.height + 2;
					
					itemX += plusBtn.width + ITEM_EDIT_BTN_X_OFFSET;
					
					world.add(plusBtn);
					world.add(minusBtn);
				}
				item.x = itemX;
				item.y = y;
				
				world.add(item);
				
				y += item.height + 8;
			}
		}
		
		public function remove():void {
			if (world) {
				world.remove(_handle);
				for each (var item:Object in _items) {
					world.remove(item.item);
				}
				world.remove(this);
			}
		}			
		
		override public function render():void {
			super.render();
			
			for each (var key:String in getOrderedItemKeys()) {
				var item:Object = _items[key];
				var p:Placeholder = item.item as Placeholder;
				var txt:Text = new Text(item.count);
				Draw.graphic(txt, p.x - txt.width, p.y + p.halfHeight);
			}
			
			Draw.rect(x+_handle.width, 0, width-_handle.width, _handle.height, 0xFFFFFF, 0.1);
		}
		
		override public function update():void {
			super.update();
		} 
		
		public function click(mX:Number, mY:Number):Boolean {
			var isClicked:Boolean = false;
			if (_handle.collidePoint(_handle.x, _handle.y, mX, mY)) {
				if (_isOpen) {
					close();
				}
				else {
					open();
				}
				isClicked = true;
			}
			else {
				for (var itemType:String in _items) {
					var p:Placeholder = _items[itemType].item as Placeholder;
					if (p.collidePoint(p.x, p.y, mX, mY)) {
						_selectedItemType = itemType;
						isClicked = true;
						break;
					}
				}
				if (!isClicked && collidePoint(_handle.width+x, y, mX, mY)) {
					isClicked = true;
				}
			}
			if (!isClicked) {
				_selectedItemType = null;
			}
			return isClicked;
		}
		
		public function open():void {
			x = FP.screen.width-width;
			_handle.x = x;
			moveItems();
			_isOpen = true;
		}
		
		public function close():void {
			x = FP.screen.width-_handle.width;
			_handle.x = x;
			moveItems();
			_isOpen = false;
		}
		
		private function moveItems():void {
			for each (var item:Object in _items) {
				var itemX:uint = this.x + _handle.width + ITEM_HANDLE_X_OFFSET;
				
				if (_isEdit) {
					var plusBtn:PlaceholderEditButton = item.plusBtn;
					plusBtn.x = itemX;
					
					(item.minusBtn as PlaceholderEditButton).x = itemX;
					
					itemX += plusBtn.width + ITEM_EDIT_BTN_X_OFFSET; 
				}
				(item.item as Placeholder).x = itemX;
			}
		}
		
		private function getOrderedItemKeys():Array {
			var keys:Array = new Array;
			
			for (var key:String in _items) {
				keys.push(key);
			}
			keys.sort();
			
			return keys;
		}
		
		public function getAllPlaceholders():Array {
			var placeholders:Array = new Array;
			
			for each (var item:Object in _items) {
				for (var i:int = 0; i < item.count; i++) {
					placeholders.push(item.item);
				}
			}
			return placeholders;
		}
		
		public function hasSelectedItem():Boolean { return _selectedItemType != null; }
		
		public function get isOpen():Boolean { return _isOpen; }
		public function get selectedItem():Placeholder {
			if (_selectedItemType) {
				var item:Object = subtractItemType(_selectedItemType, (_isEdit ? 0: 1));
				if (item) {
					var p:Placeholder = item.item as Placeholder;
					var ClassRef:Class = getDefinitionByName(_selectedItemType) as Class;
					_selectedItemType = null;
					return (new ClassRef(p.x, p.y) as Placeholder);
				}
				
			}
			return null;
		}
		
		public function get isEdit():Boolean { return _isEdit; }
	}
}